package com.dean.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.dean.dao.DeanToolDao;
import com.dean.entity.SysDbConnInfo;
import com.dean.entity.TableField;
import com.dean.entity.TableInfo;
import com.dean.exception.DeanRuntimeException;
import com.dean.sql.factory.DeanAutoSqlFactory;
import com.dean.sql.service.DeanSql;
import com.dean.utils.DeanEntityUtils;
import com.dean.utils.DeanJdbcUtils;
import com.dean.utils.FreemarkerUtils;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName EntityGenerateService
 * @Description 实体类生成工具类
 * @Author Administrator
 * @Date 2021/10/2313:36
 */
public class CodeGenerateService {
    private CodeGenerateService(){
    }
    private static volatile CodeGenerateService INSTANCE;
    public static CodeGenerateService getInstance(){
        if(INSTANCE == null){
            synchronized (CodeGenerateService.class){
                if(INSTANCE == null){
                    INSTANCE = new CodeGenerateService();
                }
            }
        }
        return INSTANCE;
    }
    /**
     * 生成实体类
     * @param tableName
     * @param filePath
     * @param packageName
     */
    private void gen(SysDbConnInfo connInfo, String tableName, String filePath, String packageName, List<String> ftls){
        if(StrUtil.isBlank(tableName)){
            DeanRuntimeException.throwException(2001,"校验错误,参数[表名-tableName]不能为空");
        }
        if(StrUtil.isBlank(filePath)){
            DeanRuntimeException.throwException(2001,"校验错误,参数[文件存放地址-filePath]不能为空");
        }
        if(StrUtil.isBlank(packageName)){
            DeanRuntimeException.throwException(2001,"校验错误,参数[基础包名-packageName]不能为空");
        }
        if(ftls==null || ftls.isEmpty()){
            DeanRuntimeException.throwException(2001,"校验错误,参数[解析模板-ftls]不能为空");
        }
        String packagePath = packageName.replace(".", File.separator);
        connInfo = DeanToolDao.getInstance().queryConnInfo(connInfo.getConnName());
        DeanSql deanSql = DeanAutoSqlFactory.getDeanSql(connInfo.getUrl());
        tableName = deanSql.covertTableName(tableName);
        // 查找表信息
        TableInfo tableInfo = DeanJdbcUtils.queryTableInfo(connInfo,deanSql.getTableInfoSql(), tableName);
        if(StrUtil.isBlank(tableInfo.getTableName())){
            DeanRuntimeException.throwException(2004,"校验错误,参数"+tableName+"未在数据库中查询到相关信息");
        }
        List<TableField> tableFieldList = DeanJdbcUtils.queryTableFields(connInfo,deanSql.getFieldInfoSql(),tableName);
        List<String> impportClasses = DeanEntityUtils.parseImportClasses(tableFieldList);
        filePath = filePath+File.separator+packagePath+File.separator;
        // 生成数据模型
        Map<String,Object> dataModel = dataModel(packageName,tableInfo,tableFieldList,impportClasses);

        final String finalFilePath = filePath;
        ftls.forEach(ftl->{
            String fileName = tableInfo.getFirstUpperEntityName()+ftl.replace("Entity","");
            // 临时添加 处理 dbs sh 脚本
            if(ftl.contains(".sh")){
                fileName =  tableInfo.getTableName().toLowerCase()+".sh";
            }else if(ftl.contains(".ktr")){
                fileName = tableInfo.getTableName().toLowerCase()+".ktr";
            }else if(ftl.contains("${EntityName}Id.java")){
                // 统计主键的数量
               long count =  tableFieldList.stream().
                        filter(tableField ->"Y".equals(tableField.getPkFlag())
                ).count();
               // 主键数量小于等于1 时不用生成额外的类
               if(count <= 1){
                   return;
               }
                fileName = ftl.replace("${EntityName}", tableInfo.getFirstUpperEntityName());
            }else{
                fileName = ftl.replace("${EntityName}", tableInfo.getFirstUpperEntityName());
            }
            FreemarkerUtils.parseTemplate(ftl+".ftl", finalFilePath,fileName,dataModel);
        });
    }

    /**
     * 生成 实体类 多表
     * @param tableNames
     * @param filePath
     * @param packageName
     */
    public void gen(SysDbConnInfo connInfo,String [] tableNames, String filePath, String packageName, List<String> ftls){
        for (String tableName : tableNames) {
            gen(connInfo,tableName,filePath,packageName,ftls);
        }
    }

    /**
     * 组成  dataModel
     * @param packageName
     * @param tableInfo
     * @param tableFields
     * @return
     */
    private Map<String,Object> dataModel(String packageName,TableInfo tableInfo,List<TableField> tableFields,List<String> importClasses){
        Map<String,Object> dataModel = new HashMap<String,Object>(16);
        dataModel.put("packageName",packageName);
        dataModel.put("tableInfo",tableInfo);
        dataModel.put("tableFields",tableFields);
        dataModel.put("importClasses",importClasses);
        dataModel.put("dateTime", DateUtil.now());
        return dataModel;
    }
}
